﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Text.RegularExpressions;
using System.IO;
using NekoVampire.TwitterClient.Controls;
using NekoVampire.TwitterClient.Twitter;
using NekoVampire.Extension;

namespace NekoVampire.TwitterClient.Forms
{
    partial class Twite
    {
        private void SendUpdate()
        {
            string str = "";
            Invoke((MethodInvoker)
                delegate
                {
                    textBox1.Enabled = false;
                    button1.Enabled = false;
                    str = textBox1.Text;
                    if (setting.addStatus)
                        str = textBox1.Text + " [Twite]";
                });

            Stream responce;
            try
            {
                if (str.StartsWith("@"))
                {
                    string user = new Regex("^@[a-zA-Z0-9_]+").Match(str).Value.Substring(1);
                    if (replyStatus.user.screenName == user)
                    {
                        responce = Twitter.SendUpdate(str, replyStatus.id);
                    }
                    else if (storage.timeLine.Exists(x => x.user.screenName == user))
                    {
                        responce = Twitter.SendUpdate(str, storage.timeLine.Last(x => x.user.screenName == user).id);
                    }
                    else
                    {
                        responce = Twitter.SendUpdate(str);
                    }
                }
                else
                {
                    responce = Twitter.SendUpdate(str);
                }
            }
            catch (WebException ex)
            {
                Invoke((MethodInvoker)
                    delegate
                    {
                        textBox1.Enabled = true;
                        button1.Enabled = true;
                        statusStrip1.Text = ex.Message;
                    });
                return;
            }

            Invoke((MethodInvoker)
                delegate
                {
                    textBox1.Text = "";
                    textBox1.Enabled = true;
                    button1.Enabled = true;
                });

            if (!thread.IsAlive)
                thread.Start();
        }

        //初期起動
        private void LoadThread()
        {
            XElement[] follow = new XElement[2];
            Invoke((MethodInvoker)delegate { toolStripStatusLabel1.Text = "起動読込[1]"; });

            try
            {
                using (Stream friend = Twitter.GetFriends())
                    follow[0] = XElement.Load(XmlReader.Create(friend));
                using (Stream followers = Twitter.GetFollowers())
                    follow[1] = XElement.Load(XmlReader.Create(followers));
            }
            catch (Exception ex)
            {
                thread = new Thread(new ThreadStart(LoadThread));
                Invoke((MethodInvoker)
                    delegate
                    {
                        timer1.Enabled = true;
                        toolStripStatusLabel1.Text = ex.Message;
                    });
                return;
            }

            lock (storage)
            {
                storage.SetFollowingList(follow[0], follow[1]);
            }
            XElement timeLine = null;
            Invoke((MethodInvoker)delegate { toolStripStatusLabel1.Text = "起動読込[1]"; });
        
            lock (Twitter)
            {
                try
                {
                    using (Stream responce = Twitter.GetTimeLine(0, setting.startupTimeLineCount))
                        timeLine = XElement.Load(XmlReader.Create(responce));
                }
                catch (Exception ex)
                {
                    thread = new Thread(new ThreadStart(LoadThread));
                    Invoke((MethodInvoker)
                        delegate
                        {
                            timer1.Enabled = true;
                            toolStripStatusLabel1.Text = ex.Message;
                        });
                    return;
                }
            }

            lock (storage)
            {
                foreach (XElement status in timeLine.Elements("status"))
                {
                    Status stat = new Status(status);
                    stat.read = true;
                    storage.AddTimeLine(stat);
                }

                Invoke((MethodInvoker)delegate { timeLineViewAdding(); });
            }
            LastTime = storage.timeLine
                .QuickSort()
                .Last(status => status.inReplyToScreenName != setting.userId && status.user.screenName != setting.userId)
                .createdAt.AddMinutes(-1);

            Invoke((MethodInvoker)delegate { toolStripStatusLabel1.Text = "起動読込[reply1]"; });

            try
            {
                using (Stream responce = Twitter.GetReplies(0))
                    timeLine = XElement.Load(XmlReader.Create(responce));
            }
            catch (Exception ex)
            {
                thread = new Thread(new ThreadStart(LoadThread));
                Invoke((MethodInvoker)
                    delegate
                    {
                        timer1.Enabled = true;
                        toolStripStatusLabel1.Text = ex.Message;
                    });
                return;
            }

            lock (storage)
            {
                foreach (XElement status in timeLine.Elements("status"))
                {
                    Status stat = new Status(status);
                    stat.read = true;
                    storage.AddTimeLine(stat);
                }
                Invoke((MethodInvoker)delegate { timeLineViewAdding(); });
            }

            if (setting.getOldStatus)
            {
                Invoke((MethodInvoker)delegate { toolStripStatusLabel1.Text = "起動読込[過去発言1]"; });

                try
                {
                    using (Stream responce = Twitter.GetUserTimeLine(setting.userId, 0, 20))
                        timeLine = XElement.Load(XmlReader.Create(responce));
                }
                catch (Exception ex)
                {
                    thread = new Thread(new ThreadStart(LoadThread));
                    Invoke((MethodInvoker)
                        delegate
                        {
                            timer1.Enabled = true;
                            toolStripStatusLabel1.Text = ex.Message;
                        });
                    return;
                }

                lock (storage)
                {
                    foreach (XElement status in timeLine.Elements("status"))
                    {
                        Status stat = new Status(status);
                        stat.read = true;
                        storage.AddTimeLine(stat);
                    }
                    Invoke((MethodInvoker)delegate { timeLineViewAdding(); });
                }
            }

            Invoke((MethodInvoker)
                delegate
                {
                    timer1.Enabled = true;
                    toolStripStatusLabel1.Text = "読み込み完了";
                });
            thread = new Thread(new ThreadStart(ReloadTimeLine));
        }

        // TL読み込み
        private void ReloadTimeLine()
        {
            if (thread2 == null ? false : thread2.IsAlive)
            {
                thread = new Thread(new ThreadStart(ReloadTimeLine));
                return;
            }
            
            Invoke((MethodInvoker)delegate { toolStripStatusLabel1.Text = "TL更新"; });
            XElement timeLine = null;
            try
            {
                using (Stream responce = Twitter.GetTimeLine(0, setting.getTimeLineCount, LastTime))
                    timeLine = XElement.Load(XmlReader.Create(responce));
            }
            catch (Exception ex)
            {
                thread = new Thread(new ThreadStart(ReloadTimeLine));
                Invoke((MethodInvoker)delegate { statusStrip1.Text = ex.Message; });
                return;
            }

            lock (storage)
            {
                thread = new Thread(new ThreadStart(ReloadTimeLine));
                foreach (XElement status in timeLine.Elements("status"))
                {
                    storage.AddTimeLine(new Status(status));
                }
                Invoke((MethodInvoker)delegate { timeLineViewAdding(); });
            }
            int i = 0;
            while (timeLine.Elements("status").Count() == setting.getTimeLineCount)
            {
                try
                {
                    using (Stream responce = Twitter.GetTimeLine(++i, setting.getTimeLineCount, LastTime))
                        timeLine = XElement.Load(XmlReader.Create(responce));
                }
                catch (Exception ex)
                {
                    thread = new Thread(new ThreadStart(ReloadTimeLine));
                    Invoke((MethodInvoker)delegate { statusStrip1.Text = ex.Message; });
                    return;
                }

                lock (storage)
                {
                    thread = new Thread(new ThreadStart(ReloadTimeLine));
                    foreach (XElement status in timeLine.Elements("status"))
                    {
                        storage.AddTimeLine(new Status(status));
                    }
                    Invoke((MethodInvoker)delegate { timeLineViewAdding(); });
                }
            }

            Invoke((MethodInvoker)delegate { toolStripStatusLabel1.Text = "Reply更新"; });

            try
            {
                using (Stream responce = Twitter.GetReplies(0, LastTime))
                    timeLine = XElement.Load(XmlReader.Create(responce));
            }
            catch (Exception ex)
            {
                thread = new Thread(new ThreadStart(ReloadTimeLine));
                Invoke((MethodInvoker)delegate { statusStrip1.Text = ex.Message; });
                return;
            }

            lock (storage)
            {
                foreach (XElement status in timeLine.Elements("status"))
                {
                    storage.AddTimeLine(new Status(status));
                }
                Invoke((MethodInvoker)delegate { timeLineViewAdding(); });
            }
            Invoke((MethodInvoker)delegate { toolStripStatusLabel1.Text = "読み込み完了"; });
            thread = new Thread(new ThreadStart(ReloadTimeLine));
            LastTime = storage.timeLine
                .Where(status => status.createdAt > LastTime)
                .QuickSort()
                .Last(status => status.inReplyToScreenName != setting.userId && status.user.screenName != setting.userId)
                .createdAt.AddMinutes(-1);
        }

        private void CreateFav(ListViewEx listView)
        {
            var select = listView.SelectedItems.Cast<ListViewItemEx>()
                .Select(p => p.Tag).ToList();

            Thread thread3 = thread2;
            thread2 = new Thread(
                new ThreadStart(delegate
                {
                    if (thread3.IsAlive)
                        thread3.Join();

                    foreach (Status selectStatus in select)
                    {
                        try
                        {
                            Twitter.CreateFav(selectStatus.id).Dispose();
                        }
                        catch (Exception)
                        {
                            Invoke((MethodInvoker)delegate
                            {
                                toolStripStatusLabel1.Text = "[" + selectStatus.id + "] Fav失敗";
                            });
                            return;
                        }
                        Invoke((MethodInvoker)delegate
                        {
                            toolStripStatusLabel1.Text = "[" + selectStatus.id + "] Fav成功";
                        });
                    }
                })
            );
            thread2.IsBackground = true;
            thread2.Start();
        }

        private void DestroyFav(ListViewEx listView)
        {
            IEnumerable<Status> select = listView.SelectedItems.Cast<ListViewItemEx>()
                .Select(p => p.Tag);

            Thread thread3 = thread2;
            thread2 = new Thread(
                new ThreadStart(delegate
                {
                    if (thread3.IsAlive)
                        thread3.Join();
                    foreach (Status selectStatus in select)
                    {
                        try
                        {
                            Twitter.DestroyFav(selectStatus.id).Dispose();
                        }
                        catch (Exception)
                        {
                            Invoke((MethodInvoker)delegate
                            {
                                toolStripStatusLabel1.Text = "[" + selectStatus.id + "] Fav失敗";
                            });
                            return;
                        }
                        Invoke((MethodInvoker)delegate
                        {
                            toolStripStatusLabel1.Text = "[" + selectStatus.id + "] Fav成功";
                        });
                        thread2.IsBackground = true;
                        thread2.Start();
                    }
                })
            );
        }
    }
}